]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
messageTray: Avoid notification double destruction after activation
authorSebastian Keller <skeller@gnome.org>
Thu, 5 Mar 2026 12:04:37 +0000 (13:04 +0100)
committerFlorian Müllner <fmuellner@gnome.org>
Sat, 14 Mar 2026 17:43:25 +0000 (18:43 +0100)
The activation handler of a notification may indirectly have already
destroyed it before `activate()` continues and tries to destroy it.

This happened for example in the `FdoNotificationDaemon` activation
handler when no default actions are specified, which ends up calling
`destroyNonResidentNotifications()`.

Another case where this could happen is the `WindowAttentionHandler`
which activates the window and upon activation of the window destroys
the entire notification source, which also destroys the notification.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5421
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/4113>
(cherry picked from commit 2fe0c2b4b23e526801ade3d54dedb578af04307c)

js/ui/messageTray.js

index bd8e8b73dd26b9c8579871ab0e861c848fa2848b..aa15ea6f1ed59fe654710286c677323ba282e51e 100644 (file)
@@ -468,8 +468,14 @@ export class Notification extends GObject.Object {
     }
 
     activate() {
+        console.assert(!this._destroyed, 'Activating a destroyed notification');
+
         this.emit('activated');
 
+        // Avoid double destruction after activation
+        if (this._destroyed)
+            return;
+
         // We don't hide a resident notification when the user invokes one of its actions,
         // because it is common for such notifications to update themselves with new
         // information based on the action. We'd like to display the updated information
@@ -483,6 +489,8 @@ export class Notification extends GObject.Object {
     destroy(reason = NotificationDestroyedReason.DISMISSED) {
         this.emit('destroy', reason);
 
+        this._destroyed = true;
+
         if (this._updateDatetimeId)
             GLib.source_remove(this._updateDatetimeId);
         delete this._updateDatetimeId;